package com.cc.visitor.utils;

import com.cc.alltype.BusinessException;
import com.cc.alltype.DatetimeUtils;
import com.cc.visitor.entity.Visit;
import com.cc.visitor.entity.wechat.MiniAccessToken;
import com.cc.visitor.entity.wechat.MiniAccessTokenUtils;
import com.cc.visitor.enums.DevMaterial;
import com.cc.visitor.service.TemplateMsgService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 小程序推送订阅消息时类似服务号推送模板消息，需要 access_token
 * 不是在管理后台设置的 token 是向微信服务器请求来的有时效的 token
 * 参见文档：https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
 * 小程序后台推送订阅消息的工具类
 * @author chanchaw
 * @create 2025-01-11 16:28
 */
@Service
public class MiniMsgUtils {
    private static final Logger logger = LoggerFactory.getLogger("wxmp");
    @Autowired
    private TemplateMsgService templateMsgService;
    private ObjectMapper mapper = new ObjectMapper();
    private static final String URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";
    private static final String TEMPLATE_ID = "M_lIUf3_vqRQsQNeaZVZ_M77QyISxago9qJ5friS35w";
    @Autowired
    private MiniAccessTokenUtils accessTokenUtils;

    private Map<String,Object> getMsgMap(){
        HashMap<String, Object> miniMsgMap = new HashMap<>();
        miniMsgMap.put("access_token", DevMaterial.VISITOR_MINI.TOKEN);
        miniMsgMap.put("template_id",TEMPLATE_ID);
        miniMsgMap.put("touser","ofF-15K2eD-76j4Vyqj25tMtHnhs");
        miniMsgMap.put("miniprogram_state","formal");
        miniMsgMap.put("lang","zh_CN");

        HashMap<String, Object> msgData = new HashMap<>();
        HashMap<String, Object> metaDataMap01 = new HashMap<>();
        metaDataMap01.put("value","张俊");
        msgData.put("name1",metaDataMap01);

        HashMap<String, Object> metaDataMap02 = new HashMap<>();
        metaDataMap02.put("value","showa");
        msgData.put("thing2",metaDataMap02);

        HashMap<String, Object> metaDataMap03 = new HashMap<>();
        metaDataMap03.put("value",DatetimeUtils.formatNow());
        msgData.put("date4",metaDataMap03);

        HashMap<String, Object> metaDataMap04 = new HashMap<>();
        metaDataMap04.put("value","审核通过");
        msgData.put("thing8",metaDataMap04);

        miniMsgMap.put("data",msgData);
        return miniMsgMap;
    }
    /**
     * 传入微信小程序订阅消息map对象，本方法将其推送给微信用户
     * @param msgMap 订阅消息对象
     */
    private void pushMiniMsg(Map<String, Object> msgMap){
        logger.info("推送小程序订阅消息：" + msgMap.toString());
        String jsonString = null;
        try {
            jsonString = mapper.writeValueAsString(msgMap);
        } catch (JsonProcessingException e) {
            logger.info("转换小程序订阅消息map对象为 jsonString 时出现异常：" + e.getMessage());
            throw new RuntimeException(e);
        }
        String ret = null;
        MiniAccessToken accessToken = accessTokenUtils.getAccessToken();
        String urlWithAccessToken = URL.replace("ACCESS_TOKEN", accessToken.getAccess_token());
        try {
            ret = HttpUtils.postJson( urlWithAccessToken, jsonString);
            logger.info("推送小程序订阅消息得到的响应：" + ret);
        } catch (Exception e) {
            logger.info("推送小程序订阅消息时出现异常：" + e.getMessage());
            throw new RuntimeException(e);
        }
    }
    private List<Object> getPushAuditedMsgData(Visit record){
        List<Object> msgDataList = new ArrayList<>();
        String intervieweeRealName = Optional.ofNullable(record.getIntervieweeRealName()).orElse("");
        LocalDateTime localDateTime = Optional.ofNullable(record.getStartTime()).orElse(LocalDateTime.now());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd HH:mm");
        String formatDatetime = localDateTime.format(dateTimeFormatter);
        msgDataList.add(intervieweeRealName);
        msgDataList.add("showa");
        msgDataList.add(formatDatetime);
        msgDataList.add("您的访单已审核通过");
        return msgDataList;
    }
    // 推送访单被审核通过的一次性订阅消息
    public void pushAudited(Visit record) {
        System.out.println("开始推送小程序订阅消息，访单已被审核通过");
        String visitorMiniId = Optional.ofNullable(record.getVisitorMiniId()).orElse("");
        if(visitorMiniId.length() == 0) throw new BusinessException("没有目标微信用户ID，无法推送已审核的订阅消息！");
        List<Object> pushAuditedMsgData = getPushAuditedMsgData(record);
        Map<String, Object> msgMap = templateMsgService.getMiniMsgMap(SysConst.MINI_MSG_PUSH_VISITOR_AUDITED,visitorMiniId,pushAuditedMsgData);
        pushMiniMsg(msgMap);
    }
    private List<Object> getPushRejectMsgData(Visit record){
        List<Object> msgDataList = new ArrayList<>();
        String intervieweeRealName = Optional.ofNullable(record.getIntervieweeRealName()).orElse("");
        LocalDateTime localDateTime = Optional.ofNullable(record.getStartTime()).orElse(LocalDateTime.now());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd HH:mm");
        String formatDatetime = localDateTime.format(dateTimeFormatter);
        msgDataList.add(intervieweeRealName);
        msgDataList.add("showa");
        msgDataList.add(formatDatetime);

        String rejectRemark = Optional.ofNullable(record.getRejectRemark()).orElse("您的访单被系统驳回");
        msgDataList.add(rejectRemark);
        return msgDataList;
    }
    public void pushReject(Visit record){
        System.out.println("开始推送小程序订阅消息，访单被驳回");
        String visitorMiniId = Optional.ofNullable(record.getVisitorMiniId()).orElse("");
        if(visitorMiniId.length() == 0) throw new BusinessException("没有目标微信用户ID，无法推送被驳回的订阅消息！");
        List<Object> pushAuditedMsgData = getPushRejectMsgData(record);
        Map<String, Object> msgMap = templateMsgService.getMiniMsgMap(SysConst.MINI_MSG_PUSH_VISITOR_REJECT,visitorMiniId,pushAuditedMsgData);
        pushMiniMsg(msgMap);
    }
}
